// $Id: XML.scala 39 2009-11-01 12:10:24Z normen.mueller $

package scala.xml.io

import java.io.{File,InputStream,FileInputStream,ByteArrayInputStream}
import java.io.{OutputStreamWriter,FileOutputStream,Writer,BufferedWriter}
import org.xml.sax.{InputSource,SAXParseException};
import scala.xml.{Node,Elem}
import scala.xml.Utility.{trim}

/** The object <code>XML</code> provides utility functions for XML operations.
 * @todo(nrm): refactore!
 */
@deprecated object XML {
   /** Nobinding adaptor providing callbacks to parser to create elements. implements hash-consing
    This adaptor excepts empyt XML trees and entirely ignores document type declarations. 
    @see scala.xml.parsing.NoBindingFactoryAdapter */
   private class NoBindingFactoryAdapter extends scala.xml.parsing.NoBindingFactoryAdapter {
     override def fatalError(ex: SAXParseException): Unit =
       if (!"Premature end of file.".equals(ex.getMessage))
         printError(ex.getMessage, ex)
         
     //@todo(nrm): Do not ignore local DTD declarations!!!
     override def resolveEntity (publicId: String, systemId: String): InputSource = {
       /* We are ignoring document type declarations so far. This deactivates the DTD. Isn't this a nice hack ;-) */                
       new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
     }
   }

   /** Loads an XML tree from file <code>file</code>.
   External document type declarations are entirely ignored. */
   def loadXML(file: File): Elem = {
     if ((file ne null) && (file.exists)) {
       try {
         trim(new NoBindingFactoryAdapter().loadXML(new InputSource(new FileInputStream(file)))).asInstanceOf[Elem]
       }
       catch {
         case ex: org.xml.sax.SAXParseException =>
           if ("Premature end of file.".equals(ex.getMessage))
             throw new Error("Premature end of file ("+file.getName+").\n"+
               "A valid XML document must contain at least one element, i.e. one empty root element.")
           else throw ex
       }
     }
     else null
   }
   
   /** Saves XML to filename with encoding UTF-8 without <code>doctype</code>. */
   def saveXML(n: Node, file: File): Boolean =
     saveXML(n,file.getAbsolutePath)
     
   /** Saves XML to filename with encoding UTF-8 without <code>doctype</code>. */
   def saveXML(n: Node, file: String): Boolean = {
     if(n ne null)
       if((file ne null) && file.length > 0) {
         // === copy of scala.xml.XML.saveFull ===
         var fos: FileOutputStream = null
         var w: Writer = null
         try {
           // using NIO classes of JDK 1.4
           import java.nio.channels.{Channels, FileChannel}
      
           fos = new FileOutputStream(file)
           w = Channels.newWriter(fos.getChannel(), "utf-8")
           write(w,n)
           true
         }
         catch {
           case ex: Exception => false
         }
         finally {
           w.close()
           fos.close()
         }
       }
       else {
         var w: Writer = null
         try {
           w = new BufferedWriter(new OutputStreamWriter(System.out))
           write(w,n)
           true
         }
         catch {
           case ex: Exception => false
         }
         finally {
           w.flush
         }
       }
     else false 
   }
     
   /** Writes the given node using writer. */
   private def write(w: java.io.Writer, n: Node) {
     w.write("<?xml version='1.0' encoding='utf-8'?>\n")
     w.write("<!-- locutor, (c) 2008, Normen Mueller, http://kwarc.info/nmueller -->\n")
     w.write("<!-- This file has been automatically generated. Do not edit! -->\n")
     //w.write(scala.xml.Utility.toXML(n))
     w.write(new scala.xml.PrettyPrinter(120,2).format(n))
   }
}
